
// code segment : 

static 
D3DFORMAT MappingFormat( GP_TYPE t, GP_INPUTPREC f )
{   // lookup table : 
    if ( t == TYPE_COLOR ) {
		if ( f == PREC_IN_08    ) return D3DFMT_R3G3B2;
        if ( f == PREC_IN_16    ) return D3DFMT_X1R5G5B5;
        if ( f == PREC_IN_32    ) return D3DFMT_X8R8G8B8;
    }
    if ( t == TYPE_COLORALPHA ) {
        if ( f == PREC_IN_16    ) return D3DFMT_A1R5G5B5;
        if ( f == PREC_IN_32    ) return D3DFMT_A8R8G8B8;
    }
	if ( t == TYPE_RCOLOR ) {
		if ( f == PREC_IN_32_16 ) return D3DFMT_G16R16;
	}
	if ( t == TYPE_RCOLORALPHA ) {
		if ( f == PREC_IN_32_10 ) return D3DFMT_A2B10G10R10;
	}
    if ( t == TYPE_DEPTH ) {
        if ( f == PREC_IN_16    ) return D3DFMT_D16;
        if ( f == PREC_IN_32    ) return D3DFMT_D32;
    }
    if ( t == TYPE_DEPTHMASK ) {
        if ( f == PREC_IN_16    ) return D3DFMT_D15S1;
        if ( f == PREC_IN_32    ) return D3DFMT_D24S8;
    }
	if ( t == TYPE_LUMIN ) {
		if ( f == PREC_IN_16    ) return D3DFMT_L6V5U5;
		if ( f == PREC_IN_16_08 ) return D3DFMT_V8U8;
		if ( f == PREC_IN_32    ) return D3DFMT_X8L8V8U8;
		if ( f == PREC_IN_32_16 ) return D3DFMT_V16U16;
	}
	if ( t == TYPE_LUMINFULL ) {
		if ( f == PREC_IN_08    ) return D3DFMT_L8;
		if ( f == PREC_IN_16_08 ) return D3DFMT_A8L8;
		if ( f == PREC_IN_32    ) return D3DFMT_Q8W8V8U8;
		if ( f == PREC_IN_32_10 ) return D3DFMT_A2W10V10U10;
	}
    throw "unrecognized type or format";
}

static 
DWORD MappingUsage( GP_OPMODE p )
{
    DWORD v = 0;
//  if ( p & OPMODE_READ ) return 0;
    if ( p & OPMODE_WRITE ) v |= D3DUSAGE_RENDERTARGET;
    return v;
}

static inline
unsigned int pow2_round(unsigned int x) { // e.g. 9 -> 16
   x = x - 1; 
   x = x | (x >> 1), x = x | (x >> 2); 
   x = x | (x >> 4), x = x | (x >> 8); 
   return x + 1; 
}

static 
void BuildVBFromMemRect(void* ptr, GP_RECT const* rects, int count) {
    VERTEX * p = (VERTEX *)ptr;
    float index = 0.0f;
    for ( int i=0; i<count; ++i, p+=4, index+=1.0f ) { // 0,0 - 1,0 - 0,1 - 1,1
        p[0].x = rects[i].pt1.x, p[0].y = rects[i].pt1.y;
        p[1].x = rects[i].pt2.x, p[1].y = rects[i].pt1.y;
        p[2].x = rects[i].pt1.x, p[2].y = rects[i].pt2.y;
        p[3].x = rects[i].pt2.x, p[3].y = rects[i].pt2.y;
        p[0].z = p[1].z = p[2].z = p[3].z = index; // auto fstep !!
        p[0].w = p[1].w = p[2].w = p[3].w = 1.0f;

        p[0].u = p[0].v = p[1].v = p[2].u = 0.0f;
        p[1].u = p[2].v = p[3].u = p[3].v = 1.0f;
    }
}
static 
void BuildVBFromMemRectT(void* ptr, GP_RECT const* rects, GP_RECT const* trects, int count) {
    VERTEX * p = (VERTEX *)ptr;
    float index = 0.0f;
    for ( int i=0; i<count; ++i, p+=4, index+=1.0f ) { // 0,0 - 1,0 - 0,1 - 1,1
		p[0].x = rects[i].pt1.x, p[0].y = rects[i].pt1.y;
        p[1].x = rects[i].pt2.x, p[1].y = rects[i].pt1.y;
        p[2].x = rects[i].pt1.x, p[2].y = rects[i].pt2.y;
        p[3].x = rects[i].pt2.x, p[3].y = rects[i].pt2.y;
        p[0].z = p[1].z = p[2].z = p[3].z = index; // auto fstep !!
        p[0].w = p[1].w = p[2].w = p[3].w = 1.0f;

		p[0].u = trects[i].pt1.x, p[0].v = trects[i].pt1.y;
		p[1].u = trects[i].pt2.x, p[1].v = trects[i].pt1.y;
		p[2].u = trects[i].pt1.x, p[2].v = trects[i].pt2.y;
		p[3].u = trects[i].pt2.x, p[3].v = trects[i].pt2.y;
    }
}
static 
void BuildVBFromMemRect(void* ptr, GP_RECT const* rects, float const* z/*4*/, float const* w/*4*/, int count) {
    VERTEX * p = (VERTEX *)ptr;
    if ( !z || !w ) return BuildVBFromMemRect(ptr, rects, count);
    for ( int i=0; i<count; ++i, p+=4 ) { // 0,0 - 1,0 - 0,1 - 1,1
        // vertex : 
        p[0].x = rects[i].pt1.x, p[0].y = rects[i].pt1.y, p[0].z = z[4*i+0], p[0].w = w[4*i+0];
        p[1].x = rects[i].pt2.x, p[1].y = rects[i].pt1.y, p[1].z = z[4*i+1], p[1].w = w[4*i+1];
        p[2].x = rects[i].pt1.x, p[2].y = rects[i].pt2.y, p[2].z = z[4*i+2], p[2].w = w[4*i+2];
        p[3].x = rects[i].pt2.x, p[3].y = rects[i].pt2.y, p[3].z = z[4*i+3], p[3].w = w[4*i+3];
        // texture coord : 
        p[0].u = p[0].v = p[1].v = p[2].u = 0.0f;
        p[1].u = p[2].v = p[3].u = p[3].v = 1.0f;
    }
}
static 
void BuildVBFromMemRectT(void* ptr, GP_RECT const* rects, float const* z/*4*/, float const* w/*4*/, GP_RECT const* trects, int count) {
    VERTEX * p = (VERTEX *)ptr;
	if ( !trects ) return BuildVBFromMemRect(ptr, rects, z, w, count);
    if ( !z || !w ) return BuildVBFromMemRectT(ptr, rects, trects, count);
    for ( int i=0; i<count; ++i, p+=4 ) { // 0,0 - 1,0 - 0,1 - 1,1
		// vertex : 
        p[0].x = rects[i].pt1.x, p[0].y = rects[i].pt1.y, p[0].z = z[4*i+0], p[0].w = w[4*i+0];
        p[1].x = rects[i].pt2.x, p[1].y = rects[i].pt1.y, p[1].z = z[4*i+1], p[1].w = w[4*i+1];
        p[2].x = rects[i].pt1.x, p[2].y = rects[i].pt2.y, p[2].z = z[4*i+2], p[2].w = w[4*i+2];
        p[3].x = rects[i].pt2.x, p[3].y = rects[i].pt2.y, p[3].z = z[4*i+3], p[3].w = w[4*i+3];
		// texture coord : 
		p[0].u = trects[i].pt1.x, p[0].v = trects[i].pt1.y;
        p[1].u = trects[i].pt2.x, p[1].v = trects[i].pt1.y;
		p[2].u = trects[i].pt1.x, p[2].v = trects[i].pt2.y;
		p[3].u = trects[i].pt2.x, p[3].v = trects[i].pt2.y;
    }
}

static 
void BuildIBFromMemRect(void* ptr, int count) {
    WORD * p = (WORD *)ptr;
    WORD index = 0;
    for ( int i=0; i<count; ++i, p+=6 ) { // template: { 0, 1, 3, 0, 3, 2, } better than { 0, 1, 2, 1, 3, 2, }
        p[0] = p[3] = index++;
        p[1] = index++;
        p[5] = index++;
        p[2] = p[4] = index++;
    }
}
